package client

import (
	"context"
	"crypto/ecdsa"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/ethclient"
	"github.com/ethereum/go-ethereum/rpc"
	"go.uber.org/zap"
	"math/big"
	"shendaNFT/config"
	"sync"
)

type EthClient struct {
	privateKey *ecdsa.PrivateKey
	client     *ethclient.Client
	chainID    *big.Int
	logger     *zap.Logger

	lock *sync.Mutex
}

func New(config config.Config, logger *zap.Logger) *EthClient {
	ctx := context.Background()
	privateKey, err := crypto.HexToECDSA(config.Ethereum.HexKey)
	if err != nil {
		logger.Sugar().Panicw("try connect blockchain failure", "error", err.Error())
		return nil
	}
	rpcClient, err := rpc.Dial(config.Ethereum.WS)
	if err != nil {
		logger.Sugar().Panicw("try connect blockchain failure", "error", err.Error())
		return nil
	}
	client := ethclient.NewClient(rpcClient)
	chainID, err := client.ChainID(ctx)
	if err != nil {
		logger.Sugar().Panicw("try connect blockchain failure", "error", err.Error())
		return nil
	}
	logger.Sugar().Debugw("connected blockchain", "ws", config.Ethereum.WS, "chainID", chainID.String())

	return &EthClient{
		privateKey: privateKey,
		client:     client,
		chainID:    chainID,
		logger:     logger,
		lock:       &sync.Mutex{},
	}
}

func (c *EthClient) NewTransactOpts() (*bind.TransactOpts, error) {
	opts, err := bind.NewKeyedTransactorWithChainID(c.privateKey, c.chainID)
	if err != nil {
		return nil, err
	}
	opts.GasPrice = big.NewInt(1000000000)
	//nonce, err := c.client.PendingNonceAt(ctx, opts.From)
	//if err != nil {
	//	return nil, err
	//}
	//opts.Nonce = big.NewInt(int64(nonce))
	return opts, nil
}
